package com.yanqu.road.entity.activity.daomu.pvp;

import com.yanqu.road.entity.activity.daomu.enums.DaoMuAttributeEnum;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * pvp属性
 */
public class DaoMuPvpProperty {

    protected static Logger logger = LogManager.getLogger(DaoMuPvpProperty.class.getName());

    /**
     * 等级
     */
    private int level;

    /**
     * 经验
     */
    private long exp;

    /**
     * 等级/经验更新时间
     */
    private long expUpdateTime;

    /**
     * 当前血量
     */
    private long curHp;

    /**
     * 基础属性(固定)
     */
    private Map<Integer, Long> baseAttributeMap = new ConcurrentHashMap<>();

    /**
     * 属性map(实时属性，含buff 、技能)
     */
    private Map<Integer, Long> attributeMap = new ConcurrentHashMap<>();

    /**
     * 复活次数
     */
    private int reviveCnt;

    /**
     * 复活时间
     */
    private long reviveTime;

    /**
     * 无敌时间
     */
    private long protectTime;

    /**
     * 学习技能次数
     */
    private int learnSkillCnt;


    /**
     * 待选择技能list
     */
    private List<Integer> chooseSkillList = new ArrayList<>();

    /**
     * 上次回血时间
     */
    private long lastHpRecoverTime;

    /**
     * 上次恢复武器时间
     */
    private long lastBulletRecoverTime;

    /**
     * 技能列表
     */
    private List<DaoMuPvpSkillData> skillDataList = new ArrayList<>();

    /**
     * buff列表
     */
    private List<DaoMuPvpBuffData> buffDataList = new ArrayList<>();


    /**
     * 战斗记录
     */
    private DaoMuPvpBattleRecord battleRecord = new DaoMuPvpBattleRecord();


    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public long getExp() {
        return exp;
    }

    public void setExp(long exp) {
        this.exp = exp;
    }

    public long getExpUpdateTime() {
        return expUpdateTime;
    }

    public void setExpUpdateTime(long expUpdateTime) {
        this.expUpdateTime = expUpdateTime;
    }

    public Map<Integer, Long> getBaseAttributeMap() {
        return baseAttributeMap;
    }

    public void setBaseAttributeMap(Map<Integer, Long> baseAttributeMap) {
        this.baseAttributeMap = baseAttributeMap;
    }

    public void setAttributeMap(Map<Integer, Long> attributeMap) {
        this.attributeMap = attributeMap;
    }

    public Map<Integer, Long> getAttributeMap() {
        return attributeMap;
    }

    public long getCurHp() {
        return curHp;
    }

    public void setCurHp(long curHp) {
        this.curHp = curHp;
    }

    public int getReviveCnt() {
        return reviveCnt;
    }

    public void setReviveCnt(int reviveCnt) {
        this.reviveCnt = reviveCnt;
    }

    public long getReviveTime() {
        return reviveTime;
    }

    public void setReviveTime(long reviveTime) {
        this.reviveTime = reviveTime;
    }

    public int getLearnSkillCnt() {
        return learnSkillCnt;
    }

    public void setLearnSkillCnt(int learnSkillCnt) {
        this.learnSkillCnt = learnSkillCnt;
    }

    public long getProtectTime() {
        return protectTime;
    }

    public void setProtectTime(long protectTime) {
        this.protectTime = protectTime;
    }

    public List<Integer> getChooseSkillList() {
        return chooseSkillList;
    }

    public void setChooseSkillList(List<Integer> chooseSkillList) {
        this.chooseSkillList = chooseSkillList;
    }

    public long getLastHpRecoverTime() {
        return lastHpRecoverTime;
    }

    public void setLastHpRecoverTime(long lastHpRecoverTime) {
        this.lastHpRecoverTime = lastHpRecoverTime;
    }

    public long getLastBulletRecoverTime() {
        return lastBulletRecoverTime;
    }

    public void setLastBulletRecoverTime(long lastBulletRecoverTime) {
        this.lastBulletRecoverTime = lastBulletRecoverTime;
    }

    /**
     * 加血
     * @param offsetHp  血量
     */
    public void addHp(long offsetHp) {
        if (offsetHp < 0) {
            return;
        }
        hpRecover();
        this.curHp = Math.min(this.curHp + offsetHp, getMaxHp());
    }

    /**
     * 扣血
     *
     * @param offsetHp 血量
     */
    public void subHp(long offsetHp) {
        if (offsetHp < 0) {
            return;
        }
        hpRecover();
        this.curHp = Math.max(0, this.curHp - offsetHp);
    }

    /**
     * 自动回血
     */
    public boolean hpRecover() {
        long nowTime = System.currentTimeMillis();
        // 死亡不自动回
        if (curHp <= 0 || nowTime < reviveTime) {
            return false;
        }
        // 判断是否有回血buff
        Long recoverHp = attributeMap.get(DaoMuAttributeEnum.ATTRIBUTE_RECOVER_HP_PVP.getType());
        if (recoverHp <= 0) {
            return false;
        }
        if (this.curHp >= getMaxHp()) {
            // 满了，不需要回了
            this.lastHpRecoverTime = nowTime;
            return false;
        }
        long offsetTime = (nowTime - lastHpRecoverTime) / 1000;
        if (offsetTime == 0) {
            return false;
        }
        // 每s恢复血量
        long addHp = recoverHp * offsetTime;
        this.curHp = Math.min(getMaxHp(), this.curHp + addHp);
        this.lastHpRecoverTime = this.lastHpRecoverTime + offsetTime * 1000;
        return true;
    }

    public long getMaxHp() {
        return attributeMap.getOrDefault(DaoMuAttributeEnum.ATTRIBUTE_HP.getType(),0L);
    }


    public List<DaoMuPvpSkillData> getSkillDataList() {
        return new ArrayList<>(skillDataList);
    }


    public void addSkill(int skillId) {
        synchronized (skillDataList) {
            boolean isFind = false;
            for (DaoMuPvpSkillData skillData : skillDataList) {
                if (skillId == skillData.getSkillId()) {
                    isFind = true;
                    skillData.setLevel(skillData.getLevel() + 1);
                    break;
                }
            }
            if (!isFind) {
                // 不存在新增一条
                skillDataList.add(new DaoMuPvpSkillData(skillId, 1));
            }
        }
    }

    /**
     * 随机移除技能(降级)
     *
     * @param cnt 次数
     */
    public void randomRemoveSkill(int cnt) {
        synchronized (skillDataList) {
            for (int i = 0; i < cnt; i++) {
                if (skillDataList.isEmpty()) {
                    return;
                }
                // 打乱下
                Collections.shuffle(skillDataList);
                DaoMuPvpSkillData randomSkill = skillDataList.get(0);
                if (randomSkill.getLevel() > 1) {
                    randomSkill.setLevel(randomSkill.getLevel() - 1);
                } else {
                    // 移除技能
                    skillDataList.remove(0);
                }
                // 记录下掉落
                addDropSkill(randomSkill.getSkillId());
            }
        }
    }

    public void addDropSkill(int skillId) {
        boolean isFind = false;
        for (DaoMuPvpSkillData skillData : battleRecord.getDropSkillList()) {
            if (skillData.getSkillId() == skillId) {
                skillData.setLevel(skillData.getLevel() + 1);
                isFind = true;
            }
        }
        if (!isFind) {
            battleRecord.getDropSkillList().add(new DaoMuPvpSkillData(skillId, 1));
        }
    }

    /**
     * 处理掉级
     * 优先处理学习次数
     * 次数不够扣待选择技能的列表，（清空当扣1次）
     * 次数不够扣技能等级 randomRemoveSkill
     */
    public void handleDropLevel(int dropLevel) {
        if (dropLevel == 0) {
            return;
        }
        // 记录下掉落等级
        battleRecord.setDropLevel(dropLevel);
        // 计算真实可以掉级的等级，角色等级不能掉到1以下
        dropLevel = Math.min(level - 1, dropLevel);
        // 最低1级
        level = Math.max(level - dropLevel, 1);
        if (learnSkillCnt >= dropLevel) {
            learnSkillCnt -= dropLevel;
            dropLevel = 0;
        } else {
            dropLevel -= learnSkillCnt;
            learnSkillCnt = 0;
        }
        if (dropLevel > 0) {
            if (!chooseSkillList.isEmpty()) {
                chooseSkillList.clear();
                dropLevel--;
            }

            if (dropLevel > 0) {
                randomRemoveSkill(dropLevel);
            }
        }
        // 等级变更也更新下时间
        expUpdateTime = System.currentTimeMillis();
    }

    public List<DaoMuPvpBuffData> getBuffDataList() {
        return new ArrayList<>(buffDataList);
    }

    /**
     * 添加buff
     *
     * @param buffId buffId
     * @param value  buff值
     * @param time   buff持续时间
     */
    public void addBuff(int buffId, long value, long time) {
        // 检验buff
        checkBuff();
        synchronized (buffDataList) {
            boolean isFind = false;
            for (DaoMuPvpBuffData buffData : buffDataList) {
                if (buffData.getBuffId() == buffId) {
                    isFind = true;
                    buffData.setValue(Math.max(buffData.getValue(), value));
                    buffData.setExpireTime(buffData.getExpireTime() + time);
                }
            }
            if (!isFind) {
                // 添加buff
                buffDataList.add(new DaoMuPvpBuffData(buffId, value, System.currentTimeMillis() + time));
            }
        }
    }

    /**
     * 检验buff
     * 移除过期buff
     */
    public boolean checkBuff() {
        synchronized (buffDataList) {
            boolean change = false;
            long nowTiem = System.currentTimeMillis();
            Iterator<DaoMuPvpBuffData> iterator = buffDataList.iterator();
            while (iterator.hasNext()) {
                DaoMuPvpBuffData data = iterator.next();
                if (data.getExpireTime() < nowTiem) {
                    // 过期了，需要移除
                    change = true;
                    iterator.remove();
                }
            }
            return change;
        }
    }

    public DaoMuPvpBattleRecord getBattleRecord() {
        return battleRecord;
    }

    public void setBattleRecord(DaoMuPvpBattleRecord battleRecord) {
        this.battleRecord = battleRecord;
    }
}
